home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 November: Tool Chest / Dev.CD Nov 94.toast / New System Software Extensions / OpenDoc A6 / OpenDoc Parts Framework / OPF / Examples / Clock / Sources / ClockPar.cpp < prev    next >
Encoding:
Text File  |  1994-04-21  |  16.2 KB  |  552 lines  |  [TEXT/MPS ]

  1. //========================================================================================
  2. //
  3. //    File:                ClockPar.cpp
  4. //    Release Version:    $ 1.0d1 $
  5. //
  6. //    Author:                Lonnie Millett
  7. //    Creation Date:        3/28/94
  8. //
  9. //    Copyright:    © 1993, 1994 by Apple Computer, Inc., all rights reserved.
  10. //
  11. //========================================================================================
  12.  
  13. #ifndef CLOCKPAR_H
  14. #include "ClockPar.h"
  15. #endif
  16.  
  17. #ifndef CLOCKFRA_H
  18. #include "ClockFra.h"
  19. #endif
  20.  
  21. #ifndef CLOCKSEL_H
  22. #include "ClockSel.h"
  23. #endif
  24.  
  25. // ----- Framework Includes -----
  26.  
  27. #ifndef BCCOLL_H
  28. #include <BCColl.h>
  29. #endif
  30.  
  31. #ifndef FWMEMMGR_H
  32. #include <FWMemMgr.h>
  33. #endif
  34.  
  35. #ifndef FWUTIL_H
  36. #include "FWUtil.h"
  37. #endif
  38.  
  39. // ----- OpenDoc Includes -----
  40.  
  41. #ifndef _STORAGEU_
  42. #include <StorageU.h>
  43. #endif
  44.  
  45. #ifndef _FRAME_
  46. #include <Frame.h>
  47. #endif
  48.  
  49. #ifndef _SHAPE_
  50. #include <Shape.h>
  51. #endif
  52.  
  53. #ifndef _WINDOW_
  54. #include <Window.h>
  55. #endif
  56.  
  57. #ifndef _MENUBAR_
  58. #include <MenuBar.h>
  59. #endif
  60.  
  61. #ifndef _FOCI_
  62. #include <Foci.h>
  63. #endif
  64.  
  65. #ifndef _FOCUSSET_
  66. #include <FocusSet.h>
  67. #endif
  68.  
  69. #ifndef _XMPSESSN_
  70. #include <XMPSessM.h>
  71. #endif
  72.  
  73. #ifndef _ARBITRAT_
  74. #include <Arbitrat.h>
  75. #endif
  76.  
  77. #ifndef _DISPTCH_
  78. #include <Disptch.h>
  79. #endif
  80.  
  81. #ifndef _EXCEPT_
  82. #include <Except.h>
  83. #endif
  84.  
  85. #ifndef _STDPROPS_
  86. #include <StdProps.h>
  87. #endif
  88.  
  89. #ifndef _CMDDEFS_
  90. #include <CmdDefs.h>
  91. #endif
  92.  
  93. #ifndef _TRANSLAT_
  94. #include <Translat.h>
  95. #endif
  96.  
  97. // ----- Macintosh Includes -----
  98.  
  99. #if defined(FW_BUILD_MAC) && !defined(__STDTYPES__)
  100. #include <StdTypes.h>
  101. #endif
  102.  
  103. #if defined(FW_BUILD_MAC) && !defined(__PACKAGES__)
  104. #include <Packages.h>
  105. #endif
  106.  
  107. #if defined(FW_BUILD_MAC) && !defined(__RESOURCES__)
  108. #include <Resources.h>
  109. #endif
  110.  
  111. #if defined(FW_BUILD_MAC) && !defined(__SOUND__)
  112. #include <Sound.h>
  113. #endif
  114.  
  115. #if defined(FW_BUILD_MAC) && !defined(__TOOLUTILS__)
  116. #include <ToolUtils.h>
  117. #endif
  118.  
  119. //==============================================================================
  120. // Constants
  121. //==============================================================================
  122.  
  123. const short kClockTypeItemID = 1;
  124.  
  125. const short kClockSoundsNoneItemID = 1;
  126. const short kClockSoundsTickItemID = 2;
  127. const short kClockSoundsChimeItemID = 3;
  128. const short kClockSoundsBothItemID = 4;
  129. const short kClockPlayChimeSoundItemID = 6;
  130.  
  131. const short kClockSoundsNone = 1;
  132. const short kClockSoundsTick = 2;
  133. const short kClockSoundsChime = 3;
  134. const short kClockSoundsBoth = 4;
  135.  
  136. const XMPFocusType kClockAudioFocus = "Audio";
  137.  
  138. const short kClockIdleFreq = 15;
  139.  
  140. #pragma segment cclockpart
  141.  
  142. //----------------------------------------------------------------------------------------
  143. // CClockPart::CClockPart
  144. //----------------------------------------------------------------------------------------
  145. CClockPart::CClockPart() :
  146.     fLastTime(0),
  147.     fClockType(kAnalogClock),
  148.     fClockSounds(kClockSoundsChime),
  149.     fChimeSound(NULL),
  150.     fTickSound(NULL),
  151.     fBackgroundPICT(NULL),
  152.     fAudioFocusToken(kXMPNullFocus),
  153.     fAudioFocusSet(NULL),
  154.     fAudioFocusFrame(NULL)
  155. {
  156. }
  157.  
  158. //----------------------------------------------------------------------------------------
  159. // CClockPart::~CClockPart
  160. //----------------------------------------------------------------------------------------
  161. CClockPart::~CClockPart()
  162. {
  163.     if (fChimeSound)
  164.         FW_CMemoryManager::FreeSystemHandle((FW_PlatformHandle)fChimeSound);
  165.     fChimeSound = NULL;
  166.  
  167.     if (fTickSound)
  168.         FW_CMemoryManager::FreeSystemHandle((FW_PlatformHandle)fTickSound);
  169.     fTickSound = NULL;
  170.  
  171.     if (fBackgroundPICT)
  172.         ::KillPicture(fBackgroundPICT);
  173.     fBackgroundPICT = NULL;
  174.         
  175.     delete fAudioFocusSet;
  176.     fAudioFocusSet = NULL;
  177. }
  178.  
  179. //----------------------------------------------------------------------------------------
  180. // CClockPart::Release
  181. //----------------------------------------------------------------------------------------
  182. void CClockPart::Release()
  183. {
  184.     FW_CPart::Release();
  185.     
  186.     if (this->GetRefCount() == 1)
  187.     {
  188.         this->GetSession()->GetDispatcher()->UnregisterIdle(this, NULL);
  189.     }
  190. }
  191.  
  192. //----------------------------------------------------------------------------------------
  193. // CClockPart::Initialize
  194. //----------------------------------------------------------------------------------------
  195. void CClockPart::Initialize()
  196. {
  197.     FW_CPart::Initialize();
  198.     
  199.     XMPSession* session = this->GetSession();
  200.     
  201.     // Register a special focus for audio so the arbitrator can arbitrate the audio focus
  202.     fAudioFocusToken = session->Tokenize(kClockAudioFocus);
  203.     
  204.     if (!session->GetArbitrator()->IsFocusRegistered(fAudioFocusToken))
  205.         session->GetArbitrator()->RegisterFocus(fAudioFocusToken,NULL);
  206.  
  207.     FW_CAcquireASLMResourceAccess aq;
  208.  
  209.     XMPMenuBar *menuBar = this->GetMenuBar();
  210.     menuBar->AddMenuLast(kClockTypeMenu, GetMenu(kClockTypeMenu), this);
  211.     menuBar->AddMenuLast(kClockSoundsMenu, GetMenu(kClockSoundsMenu), this);
  212.  
  213.     menuBar->RegisterCommand(cClockType, kClockTypeMenu, kClockTypeItemID);
  214.     menuBar->RegisterCommand(cClockSoundsNone, kClockSoundsMenu, kClockSoundsNoneItemID);
  215.     menuBar->RegisterCommand(cClockSoundsTick, kClockSoundsMenu, kClockSoundsTickItemID);
  216.     menuBar->RegisterCommand(cClockSoundsChime, kClockSoundsMenu, kClockSoundsChimeItemID);
  217.     menuBar->RegisterCommand(cClockSoundsBoth, kClockSoundsMenu, kClockSoundsBothItemID);
  218.     menuBar->RegisterCommand(cClockPlayChimeSound, kClockSoundsMenu, kClockPlayChimeSoundItemID);
  219.     menuBar->CheckCommand(cClockSoundsChime, TRUE);
  220.     
  221.     // Get default clock sounds
  222.     fChimeSound = ::GetResource(soundListRsrc, kClockChime);
  223.     ::DetachResource(fChimeSound);
  224.     
  225.     fTickSound = ::GetResource(soundListRsrc, kClockTick);
  226.     ::DetachResource(fTickSound);
  227.     
  228.     // Create a new focus set which just contains the speaker.  This focus will be
  229.     // aquired before playing the clock sounds
  230.     fAudioFocusSet = new XMPFocusSet;
  231.     fAudioFocusSet->InitFocusSet();
  232.     fAudioFocusSet->Add(this->GetAudioFocusToken());
  233.  
  234.     unsigned long time;
  235.     GetDateTime(&time);
  236.     this->SetLastTime(time);
  237.  
  238.     this->GetSession()->GetDispatcher()->RegisterIdle(this, NULL, kClockIdleFreq);
  239. }
  240.  
  241. //------------------------------------------------------------------------------
  242. // CClockPart::InternalizeContent
  243. //------------------------------------------------------------------------------
  244. void CClockPart::InternalizeContent(XMPStorageUnit* storageUnit)
  245. {
  246.     storageUnit->Focus(kXMPPropContents, kXMPPosUndefined, this->GetContentPropertyValueType(), 0, kXMPPosUndefined);
  247.     
  248.     storageUnit->GetValue(sizeof(fClockType), (XMPValue)&fClockType);    
  249.     storageUnit->GetValue(sizeof(fClockSounds), (XMPValue)&fClockSounds);
  250.     
  251.     unsigned long chimeSize = storageUnit->GetSize();
  252.     FW_PlatformHandle chimeHandle = FW_CMemoryManager::AllocateSystemHandle(chimeSize);
  253.     THROW_IF_NULL(chimeHandle);
  254.     
  255.     FW_CMemoryManager::LockSystemHandle(chimeHandle);
  256.     storageUnit->GetValue(chimeSize, (XMPValue)*chimeHandle);
  257.     FW_CMemoryManager::UnlockSystemHandle(chimeHandle);
  258.     this->SetChimeSound(chimeHandle);
  259.     
  260.     FW_Boolean hasPicture;
  261.     storageUnit->GetValue(sizeof(FW_Boolean), (XMPValue)&hasPicture);
  262.     if (hasPicture)
  263.     {
  264.         unsigned long pictSize = storageUnit->GetSize();
  265.         PicHandle pictHandle = (PicHandle) FW_CMemoryManager::AllocateSystemHandle(pictSize);
  266.         THROW_IF_NULL(pictHandle);
  267.         
  268.         FW_CMemoryManager::LockSystemHandle((FW_PlatformHandle)pictHandle);
  269.         storageUnit->GetValue(pictSize, (XMPValue)*pictHandle);
  270.         FW_CMemoryManager::UnlockSystemHandle((FW_PlatformHandle)pictHandle);
  271.         this->SetBackgroundPICT(pictHandle);
  272.     }
  273. }
  274.  
  275. //----------------------------------------------------------------------------------------
  276. // CClockPart::ExternalizeContent
  277. //----------------------------------------------------------------------------------------
  278. void CClockPart::ExternalizeContent(XMPStorageUnit* storageUnit)
  279. {
  280.     storageUnit->Focus(kXMPPropContents, kXMPPosUndefined, this->GetContentPropertyValueType(), 0, kXMPPosUndefined);
  281.  
  282.     storageUnit->SetValue(sizeof(fClockType), (XMPValue)&fClockType);
  283.     storageUnit->SetValue(sizeof(fClockSounds), (XMPValue)&fClockSounds);
  284.     
  285.     FW_CMemoryManager::LockSystemHandle(fChimeSound);
  286.     storageUnit->SetValue(FW_CMemoryManager::GetSystemHandleSize(fChimeSound), (XMPValue)*fChimeSound);
  287.     FW_CMemoryManager::UnlockSystemHandle(fChimeSound);
  288.     
  289.     if (fBackgroundPICT)
  290.     {
  291.         FW_Boolean hasPicture = TRUE;
  292.         storageUnit->SetValue(sizeof(FW_Boolean), (XMPValue)&hasPicture);
  293.         
  294.         FW_CMemoryManager::LockSystemHandle((FW_PlatformHandle)fBackgroundPICT);
  295.         storageUnit->SetValue(FW_CMemoryManager::GetSystemHandleSize((FW_PlatformHandle)fBackgroundPICT), (XMPValue)*fBackgroundPICT);
  296.         FW_CMemoryManager::UnlockSystemHandle((FW_PlatformHandle)fBackgroundPICT);
  297.     }
  298. }
  299.  
  300. //----------------------------------------------------------------------------------------
  301. // CClockPart::GetContentPropertyValueType
  302. //----------------------------------------------------------------------------------------
  303. XMPValueType CClockPart::GetContentPropertyValueType() const
  304. {
  305.     return kSampleClockKind;
  306. }
  307.  
  308. //----------------------------------------------------------------------------------------
  309. // CClockPart::NewFrame
  310. //----------------------------------------------------------------------------------------
  311. FW_CFrame* CClockPart::NewFrame(XMPFrame* xmpFrame, XMPTypeToken presentation)
  312. {
  313.     FW_UNUSED(presentation);
  314.     
  315.     CClockFrame *frame = new CClockFrame();
  316.     frame->InitClockFrame(xmpFrame, this);
  317.     return frame;
  318. }
  319.  
  320. //----------------------------------------------------------------------------------------
  321. // CClockPart::DoIdle
  322. //----------------------------------------------------------------------------------------
  323. FW_Boolean CClockPart::DoIdle()
  324. {
  325.     unsigned long tickCount;
  326.     DateTimeRec time;
  327.     DateTimeRec lastTime;
  328.     
  329.      ::GetDateTime(&tickCount);
  330.     ::Secs2Date(tickCount, &time);
  331.     ::Secs2Date(this->GetLastTime(), &lastTime);
  332.     
  333.      if (lastTime.second != time.second)
  334.     {
  335.         short clockSound = this->GetClockSounds();
  336.         if (clockSound != kClockSoundsNone)
  337.         {
  338.             // Ask for the audio focus so we can play sound and keep it for as long as we can
  339.             // It would be nice if focus abitration could be at the part level just like idling
  340.             // but for now it belongs to the frame
  341.             FW_Boolean hasSoundFocus = FALSE;
  342.             XMPArbitrator* arbitrator = this->GetSession()->GetArbitrator();
  343.             if (arbitrator->GetFocusOwner(this->GetAudioFocusToken()) != fAudioFocusFrame)
  344.                 hasSoundFocus = arbitrator->RequestFocusSet(fAudioFocusSet, fAudioFocusFrame);
  345.             else
  346.                 hasSoundFocus = TRUE;
  347.                 
  348.             if (hasSoundFocus)
  349.             {
  350.                 if ((clockSound == kClockSoundsTick) || (clockSound == kClockSoundsBoth))
  351.                     this->PlayTickSound();
  352.                 if (((clockSound == kClockSoundsChime) || (clockSound == kClockSoundsBoth)) &&
  353.                         (time.minute == 0) && (time.second == 0))
  354.                     this->PlayChimeSound();
  355.             }
  356.         }
  357.         
  358.         // Update all the display frames of the same type
  359.         BC_TCollectionActiveIterator<FW_CFrame*> iter(*this->GetDisplayFrameList());
  360.         while (!iter.IsDone())
  361.         {
  362.             ((CClockFrame*)*iter.CurrentItem())->UpdateClock(tickCount);
  363.             iter.Next();
  364.         }
  365.  
  366.         this->SetLastTime(tickCount);
  367.     }
  368.     return TRUE;
  369. }
  370.  
  371. //------------------------------------------------------------------------------
  372. // CClockPart::DoMenuEvent
  373. //------------------------------------------------------------------------------
  374. FW_Boolean CClockPart::DoMenuEvent(XMPMenuBar* menuBar, XMPCommandID commandID)
  375. {
  376.     FW_Boolean menuHandled = FALSE;
  377.     
  378.     switch (commandID)
  379.     {
  380.         case cClockType:
  381.                 {
  382.                     if (this->GetClockType() == kAnalogClock)
  383.                         this->SetClockType(kDigitalClock);
  384.                     else
  385.                         this->SetClockType(kAnalogClock);
  386.                         
  387.                     FW_CPartFrameIterator iter(this, this->GetDefaultPresentation());
  388.                     while (!iter.IsDone())
  389.                     {
  390.                         this->FrameShapeChanged(iter.CurrentItem()->GetXMPFrame());
  391.                         iter.Next();
  392.                     }
  393.                 }
  394.                     
  395.                 menuHandled = TRUE;
  396.                 break;
  397.                 
  398.         case cClockSoundsNone:
  399.                 this->SetClockSounds(kClockSoundsNone);
  400.                 menuHandled = TRUE;
  401.                 break;
  402.  
  403.         case cClockSoundsTick:
  404.                 this->SetClockSounds(kClockSoundsTick);
  405.                 menuHandled = TRUE;
  406.                 break;
  407.  
  408.         case cClockSoundsChime:
  409.                 this->SetClockSounds(kClockSoundsChime);
  410.                 menuHandled = TRUE;
  411.                 break;
  412.  
  413.         case cClockSoundsBoth:
  414.                 this->SetClockSounds(kClockSoundsBoth);
  415.                 menuHandled = TRUE;
  416.                 break;
  417.  
  418.         case cClockPlayChimeSound:
  419.                 this->PlayChimeSound();
  420.                 menuHandled = TRUE;
  421.                 break;
  422.  
  423.         default:
  424.             menuHandled = FW_CPart::DoMenuEvent(menuBar, commandID);
  425.     }            
  426.     
  427.     return menuHandled;
  428. }
  429.  
  430. //----------------------------------------------------------------------------------------
  431. // CClockPart::DoAdjustMenus
  432. //----------------------------------------------------------------------------------------
  433. void CClockPart::DoAdjustMenus(XMPMenuBar* menuBar)
  434. {
  435.     Str255 menuString;
  436.     
  437.     FW_CAcquireASLMResourceAccess aq;
  438.  
  439.     XMPTranslation *translate = GetSession()->GetTranslation();
  440.     XMPType PICTType = translate->GetISOTypeFromPlatformType('PICT', kXMPPlatformDataType);
  441.     XMPType sndType = translate->GetISOTypeFromPlatformType('snd ', kXMPPlatformDataType);
  442.  
  443.     // We should use kXMPApplesnd here but it is currently defined wrong
  444.     // Just type cast the string for right now
  445.     if (HasPropertyOnClipboard(kXMPPropContents, PICTType) ||
  446.              HasPropertyOnClipboard(kXMPPropContents, (XMPValueType)sndType))
  447.         menuBar->EnableCommand(kXMPCommandPaste, TRUE);
  448.  
  449.     if (this->GetClockType() == kAnalogClock)
  450.         GetIndString(menuString, kClockPartStrings, kClockDigitalMenuString);
  451.     else
  452.         GetIndString(menuString, kClockPartStrings, kClockAnalogMenuString);
  453.     menuBar->SetItemString(cClockType, menuString);
  454.     
  455.     // Uncheck them all then check the correct one
  456.     menuBar->CheckCommand(cClockSoundsNone, FALSE);
  457.     menuBar->CheckCommand(cClockSoundsTick, FALSE);
  458.     menuBar->CheckCommand(cClockSoundsChime, FALSE);
  459.     menuBar->CheckCommand(cClockSoundsBoth, FALSE);
  460.     
  461.     switch(this->GetClockSounds())
  462.     {
  463.         case kClockSoundsNone:
  464.             menuBar->CheckCommand(cClockSoundsNone, TRUE);
  465.             break;
  466.         case kClockSoundsTick:
  467.             menuBar->CheckCommand(cClockSoundsTick, TRUE);
  468.             break;
  469.         case kClockSoundsChime:
  470.             menuBar->CheckCommand(cClockSoundsChime, TRUE);
  471.             break;
  472.         case kClockSoundsBoth:
  473.             menuBar->CheckCommand(cClockSoundsBoth, TRUE);
  474.             break;
  475.     }
  476. }
  477.  
  478.  
  479. //----------------------------------------------------------------------------------------
  480. // CClockPart::AddDisplayFrame
  481. //----------------------------------------------------------------------------------------
  482. void CClockPart::AddDisplayFrame(XMPFrame* xmpFrame)
  483. {
  484.     FW_CPart::AddDisplayFrame(xmpFrame);
  485.     
  486.     if (!fAudioFocusFrame)
  487.         fAudioFocusFrame = xmpFrame;
  488. }
  489.  
  490. //----------------------------------------------------------------------------------------
  491. // CClockPart::RemoveDisplayFrame
  492. //----------------------------------------------------------------------------------------
  493. void CClockPart::RemoveDisplayFrame(XMPFrame* xmpFrame)
  494. {
  495.     if (xmpFrame == fAudioFocusFrame)
  496.     {
  497.         XMPArbitrator* arbitrator = this->GetSession()->GetArbitrator();
  498.         arbitrator->RelinquishFocusSet(fAudioFocusSet, fAudioFocusFrame);
  499.         fAudioFocusFrame = NULL;
  500.     }
  501.     FW_CPart::RemoveDisplayFrame(xmpFrame);
  502. }
  503.  
  504. //----------------------------------------------------------------------------------------
  505. // CClockPart::PlayTickSound
  506. //----------------------------------------------------------------------------------------
  507. void CClockPart::PlayTickSound()
  508. {
  509.     ::SndPlay(NULL, fTickSound, TRUE);
  510. }
  511.  
  512. //----------------------------------------------------------------------------------------
  513. // CClockPart::PlayChimeSound
  514. //----------------------------------------------------------------------------------------
  515. void CClockPart::PlayChimeSound()
  516. {
  517.     ::SndPlay(NULL, fChimeSound, TRUE);
  518. }
  519.  
  520. //----------------------------------------------------------------------------------------
  521. // CClockPart::NewSelection
  522. //----------------------------------------------------------------------------------------
  523. FW_CSelection* CClockPart::NewSelection()
  524. {
  525.     CClockSelection* clockSelection = new CClockSelection;
  526.     clockSelection->InitClockSelection(this);
  527.     return clockSelection;
  528. }
  529.  
  530. //----------------------------------------------------------------------------------------
  531. // CClockPart::SetChimeSound
  532. //----------------------------------------------------------------------------------------
  533. void CClockPart::SetChimeSound(FW_PlatformHandle chimeSound)
  534. {
  535.     if (fChimeSound)
  536.         FW_CMemoryManager::FreeSystemHandle(fChimeSound);
  537.     
  538.     fChimeSound = chimeSound;
  539. }
  540.  
  541. //----------------------------------------------------------------------------------------
  542. // CClockPart::SetBackgroundPICT
  543. //----------------------------------------------------------------------------------------
  544. void CClockPart::SetBackgroundPICT(PicHandle backgroundPICT)
  545. {
  546.     if (fBackgroundPICT)
  547.         ::KillPicture(fBackgroundPICT);
  548.     
  549.     fBackgroundPICT = backgroundPICT;
  550. }
  551.  
  552.